#pragma once

#include <queue>
#include "Thread.h"
#include "Mutex.h"
#include "Cond.h"

namespace zmh
{
#define DEFAULT_CAPACITY 5 // block_queue default size

    template <class T>
    class block_queue
    {
    public:
        block_queue(unsigned int capacity = DEFAULT_CAPACITY) : _capacity(capacity) {}

        void producer(const T &data)
        {
            auto_Mutex guard_mutex(_mutex);
            while (size() == _capacity)
            {
                _cond_producer.wait(_mutex);
            }
            _qu.emplace(data);
            _cond_consumer.signal();
        }
        T consumer()
        {
            auto_Mutex guard_mutex(_mutex);
            while (size() == 0)
            {
                _cond_consumer.wait(_mutex);
            }
            T data = _qu.front();
            _qu.pop();
            _cond_producer.signal();
            return data;
        }
        unsigned int size()
        {
            return _qu.size();
        }

    private:
        std::queue<T> _qu;      // 所用的容器
        unsigned int _capacity; // 容量大小
        Mutex _mutex;           // 互斥锁
        Cond _cond_producer;    // 条件变量 for 生成者
        Cond _cond_consumer;    // 条件变量 for 消费者
    };
}